package com.jzy.stock.wareHoursePosition.service.impl;


import com.jzy.stock.kufangguishu.model.KuWeiVo;
import com.jzy.stock.util.*;
import com.jzy.stock.wareHoursePosition.mapper.WareHoursePositionMapper;
import com.jzy.stock.wareHoursePosition.model.*;
import com.jzy.stock.wareHoursePosition.service.WareHoursePositionService;
import io.swagger.models.auth.In;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import java.io.InputStream;
import java.util.*;

@Service
public class WareHoursePositionServiceImpl implements WareHoursePositionService {

    @Autowired
    private WareHoursePositionMapper wareHoursePositionMapper;

    @Override
    public ResultVo queryPage(SelectVo selectVo) {
        List<WareHoursePositionVo> positionVos = wareHoursePositionMapper.queryData(selectVo);
        for (WareHoursePositionVo WareHoursePositionVo : positionVos) {
            //Boolean转int  三元表达式可以做到
            Integer status = WareHoursePositionVo.getStatus() ? 1 : 0;
            WareHoursePositionVo.setStatusName(StatusEnum2.queryNameByStatus(status));
        }
        //查询数量
        int count = wareHoursePositionMapper.queryCount(selectVo);
        AllRecordsVo allRecordsVo = new AllRecordsVo();
        allRecordsVo.setDataList(positionVos);//数据
        allRecordsVo.setPageIndex(selectVo.getPageIndex());
        allRecordsVo.setPageSize(selectVo.getPageSize());
        allRecordsVo.setTotalNumber(count);//总数量
        allRecordsVo.setTotalPage(allRecordsVo.countPage(count));//给总页数赋值

        return ResultBuildVo.success(allRecordsVo);
    }

    @Override
    public ResultVo add(ListVo listVo) {

        List<KuWeiVo> kuWeiVos = wareHoursePositionMapper.queryAllKuwei();
        List<AddVo> contentList = listVo.getContentList();
        String storageSectionCode = null;
        //如果前端有没有删除的库位信息 就把和数据库匹配到的库位信息的法人code
        // 赋值给添加的对象中的法人code字段
        for (AddVo addVo : contentList) {
            for (KuWeiVo kuWeiVo : kuWeiVos) {
                if (addVo.getCode().equals(kuWeiVo.getCode())) {
                    addVo.setLegalPersonCode(kuWeiVo.getLegalPersonCode());
                    addVo.setStatus(kuWeiVo.getStatus());
                    storageSectionCode = addVo.getStorageSectionCode();
                }
            }
        }
        listVo.setContentList(contentList);

        //先删除没有法人外键的库位
        wareHoursePositionMapper.delete(storageSectionCode);

        List<AddVo> list = new ArrayList<>();
        for (AddVo addVos : listVo.getContentList()) {
            IwnXiaLaVo iwnXiaLaVos = wareHoursePositionMapper.queryByCode(addVos.getCode());
            if (iwnXiaLaVos == null) {
                list.add(addVos);
            }
        }
        if (list.size() != 0) {
            listVo.setContentList(list);
            wareHoursePositionMapper.add(listVo);
            return ResultBuildVo.success();
        }
        return ResultBuildVo.success();
    }

    @Override
    public ResultVo update(@Valid UpdateVo updateVo) {
        //必须禁用才能修改
        WareHoursePositionVo wareHoursePositionVo = wareHoursePositionMapper.queryById(updateVo.getId());
        if (wareHoursePositionVo == null) {
            return ResultBuildVo.error("修改数据不存在！");
        }
        if (wareHoursePositionVo.getStatus()) {
            return ResultBuildVo.error("必须是禁用才能修改！");
        }

        WareHoursePositionVo hoursePositionVo = new WareHoursePositionVo();
        // 注意：参数名称必须一致，参数类型必须一致。
        BeanUtils.copyProperties(updateVo, hoursePositionVo);
        wareHoursePositionMapper.update(hoursePositionVo);
        return ResultBuildVo.success();
    }

    @Override
    public ResultVo updateStatus(@Valid UpdateStatusVo updateStatusVo) {
        WareHoursePositionVo wareHoursePositionVo = wareHoursePositionMapper.queryById(updateStatusVo.getId());
        if (wareHoursePositionVo == null) {
            return ResultBuildVo.error("修改数据不存在！");
        }
        WareHoursePositionVo wareHoursePositionVo1 = new WareHoursePositionVo();
        // BeanUtils.copyProperties  把左边对象的参数值 赋值给右边对象的参数值，
        // 注意：参数名称必须一致，参数类型必须一致。
        BeanUtils.copyProperties(updateStatusVo, wareHoursePositionVo1);
        wareHoursePositionMapper.updateEnabled(wareHoursePositionVo1);
        return ResultBuildVo.success();
    }

/*    @Override
    public ResultVo queryWareHouse() {
        List<WareHouseVo> wareHouseVo = wareHoursePositionMapper.queryXiaLaWareHouse();
        return ResultBuildVo.success(wareHouseVo);
    }*/

    @Override
    public ResultVo queryStorageSection(Integer id) {
        List<StorageSectionVo> storageSectionVos = wareHoursePositionMapper.queryXiaLaStorageSectionVo(id);
        return ResultBuildVo.success(storageSectionVos);
    }

    @Override
    public ResultVo queryStorageBin(IwnVo iwnVo) {
        List<StorageSectionVo> iwnXiaLaVos = wareHoursePositionMapper.queryStorageBin(iwnVo);
        return ResultBuildVo.success(iwnXiaLaVos);
    }

    @Override
    public ResultVo queryLegalPersonNameByUserId(int id) {
        List<LegalPersonVo> legalPersonVo = wareHoursePositionMapper.queryLegalPersonNameByUserId(id);
        return ResultBuildVo.success(legalPersonVo);
    }


    //库位导入
    @Override
    @Transactional
    public ResultVo importFile(MultipartFile file) throws Exception {
        //1.验证是否文件为空
        if (file == null) {
            return ResultBuildVo.error("导入文件不能为空！");
        }
        //验证模板是否正确
        if (!file.getOriginalFilename().contains("xlsx")) {
            return ResultBuildVo.error("必须是2007版本的Excel，必须是xlsx结尾的EXCEL文件");
        }
        //验证是否是正确的模板
        XSSFWorkbook workbook = new XSSFWorkbook(file.getInputStream());
        //获取单元格中的信息 at0是获取sheet1中的数据。
        XSSFSheet sheet = workbook.getSheetAt(0);
        XSSFCell cell = sheet.getRow(0).getCell(0);
        String neirong = cell.getStringCellValue();
        if (!neirong.equals("库位信息导入")) {
            return ResultBuildVo.error("模板错误，必须导入库位信息模板内容");
        }
        //使用poi读取excel表格内容放入到list
        ResultVo<List<ImportVo>> resultVo = readFile(sheet);
        if (!resultVo.getSuccess()) {
            return resultVo;
        }
        //验证导入数据
        List<ImportVo> importVoList = resultVo.getData();
        ResultVo validata = validata(importVoList);
        if (!validata.getSuccess()) {
            return validata;
        }
        //验证导入数据是否重复
        ResultVo resultVo1 = validataRepeat(importVoList);
        if (!resultVo1.getSuccess()) {
            return resultVo1;
        }
        //验证导入数据是否与数据库数据重复11
        //批量验证名称是否重复
        List<String> nameList = new ArrayList<>();
        List<String> codeList = new ArrayList<>();
        List<String> storageSectionCodeList = new ArrayList<>();
        List<String> legalPersonCodeList = new ArrayList<>();
        for (ImportVo importVo : importVoList) {
            nameList.add(importVo.getName());
            codeList.add(importVo.getCode());
            storageSectionCodeList.add(importVo.getStorageSectionCode());
            legalPersonCodeList.add(importVo.getLegalPersonCode());
        }
        List<String> names = wareHoursePositionMapper.queryByNames(nameList);
        if (!CollectionUtils.isEmpty(names)) {
            return ResultBuildVo.error("名称已经存在,存在的名称是" + names);
        }
        //批量验证编码是否重复
        List<String> codes = wareHoursePositionMapper.queryByCodes(codeList);
        if (!CollectionUtils.isEmpty(codes)) {
            return ResultBuildVo.error("编码已经存在,存在的编码是" + codes);
        }
        //批量验证库区编码是否存在
        List<String> storageSectionCodes = wareHoursePositionMapper.queryByStorageSectionCodes(storageSectionCodeList);
        if (storageSectionCodes.size() == 0) {
            return ResultBuildVo.error("库区编码不存在，不存在的库区编码是" + storageSectionCodes);

        }
        //批量验证法人编码是否存在
        List<String> legalPersonCodes = wareHoursePositionMapper.queryByLegalPersonCodes(legalPersonCodeList);
        if (legalPersonCodes.size() == 0) {
            return ResultBuildVo.error("法人编码不存在，不存在的法人编码是" + legalPersonCodes);

        }
        //批量入库
        wareHoursePositionMapper.importFile(importVoList);
        return ResultBuildVo.success();
    }

    //使用poi读取excel表格内容放入到list
    public ResultVo readFile(XSSFSheet sheet) {
        List<ImportVo> importVoList = new ArrayList<>();
        for (int i = 2; i <= sheet.getLastRowNum(); i++) {
            //   格式是否正确
            try {
                String name = String.valueOf(sheet.getRow(i).getCell(1)).trim();
                String code = String.valueOf(sheet.getRow(i).getCell(2)).trim();
                String status = String.valueOf(sheet.getRow(i).getCell(3)).trim();
                String storageSectionCode = String.valueOf(sheet.getRow(i).getCell(4)).trim();
                String legalPersonCode = String.valueOf(sheet.getRow(i).getCell(5)).trim();
                if (!code.equals("null") && !code.equals("") || !name.equals("null") && !name.equals("") || !status.equals("null") && !status.equals("") || !storageSectionCode.equals("null") && !storageSectionCode.equals("") || !legalPersonCode.equals("null") && !legalPersonCode.equals("")) {
                    ImportVo importVo = new ImportVo();
                    importVo.setXuHao(String.valueOf(sheet.getRow(i).getCell(0)));
                    importVo.setName(String.valueOf(sheet.getRow(i).getCell(1)));
                    importVo.setCode(String.valueOf(sheet.getRow(i).getCell(2)));
                    importVo.setStatusName(String.valueOf(sheet.getRow(i).getCell(3)));
                    importVo.setStorageSectionCode(String.valueOf(sheet.getRow(i).getCell(4)));
                    importVo.setLegalPersonCode(String.valueOf(sheet.getRow(i).getCell(5)));
                    importVoList.add(importVo);
                }
            } catch (Exception e) {
                return ResultBuildVo.error("格式有问题，必须是文本格式。");
            }
        }
        return ResultBuildVo.success(importVoList);
    }

    //5.验证字段长度、是否为空
    public ResultVo validata(List<ImportVo> importVoList) {
        for (ImportVo importVo : importVoList) {
            //验证名称
            if (importVo.getName() == null) {
                return ResultBuildVo.error("序号：" + importVo.getXuHao() + "名称不能为空");
            } else {
                if (importVo.getName().length() > 100) {
                    return ResultBuildVo.error("序号：" + importVo.getXuHao() + ",名称不能太长！");
                }
            }
            //验证编码
            if (importVo.getCode() == null) {
                return ResultBuildVo.error("序号：" + importVo.getXuHao() + "编码不能为空");
            } else {
                if (importVo.getCode().length() > 100) {
                    return ResultBuildVo.error("序号：" + importVo.getXuHao() + ",编码不能太长！");
                }
            }
            //验证状态并转换类型
            if (StatusEnum.queryIdByName(importVo.getStatusName()) == null) {
                return ResultBuildVo.error("序号：" + importVo.getXuHao() + ",状态只能填写启用或者禁用！");
            } else {
                if (StatusEnum.queryIdByName(importVo.getStatusName()) == 1) {
                    importVo.setStatus(true);
                } else {
                    importVo.setStatus(false);
                }
            }
            //验证库区编码
            if (importVo.getStorageSectionCode() == null) {
                return ResultBuildVo.error("序号：" + importVo.getXuHao() + "库区编码不能为空");
            } else {
                if (importVo.getStorageSectionCode().length() > 100) {
                    return ResultBuildVo.error("序号：" + importVo.getXuHao() + ",库区编码不能太长！");
                }
            }
            //验证法人编码
            if (importVo.getLegalPersonCode() == null) {
                return ResultBuildVo.error("序号：" + importVo.getXuHao() + "法人编码不能为空");
            } else {
                if (importVo.getLegalPersonCode().length() > 100) {
                    return ResultBuildVo.error("序号：" + importVo.getXuHao() + ",法人编码不能太长！");
                }
            }
        }
        return ResultBuildVo.success();
    }

    //验证导入数据是否重复
    public ResultVo validataRepeat(List<ImportVo> importVoList) {
        //去重编码字段
        List<String> codes = new ArrayList<>();
        for (ImportVo importVo : importVoList) {
            codes.add(importVo.getCode());
        }
        List<String> codeAll = new ArrayList<>();
        Set<String> repeatCode = new HashSet<>();
        for (String code : codes) {
            if (codeAll.contains(code)) {
                repeatCode.add(code);
            } else {
                codeAll.add(code);
            }
        }
        if (repeatCode.size() > 0) {
            return ResultBuildVo.error("存在重复的编码，重复的编码是：" + repeatCode);
        }
        //去重名称字段
        List<String> names = new ArrayList<>();
        for (ImportVo importVo : importVoList) {
            names.add(importVo.getName());
        }
        List<String> nameAll = new ArrayList<>();
        Set<String> repeatName = new HashSet<>();
        for (String name : names) {
            if (codeAll.contains(name)) {
                repeatName.add(name);
            } else {
                nameAll.add(name);
            }
        }
        if (repeatName.size() > 0) {
            return ResultBuildVo.error("存在重复的名称，重复的名称是：" + repeatName);
        }
       /* //去重一组数据   对象
        List<ImportVo> result = importVoList.stream().collect(
                Collectors.collectingAndThen(
                        Collectors.toCollection(
                                () -> new TreeSet<ImportVo>(Comparator.comparing(p -> p.getCode() + ";" + p.getName()+ ";" + p.getStorageSectionCode()+ ";" + p.getLegalPersonCode()))), ArrayList::new));

        if (result.size() > 0) {
            return ResultBuildVo.error("存在重复的一组数据，重复的数据是：" + result);
        }*/

        return ResultBuildVo.success();
    }

    //库位导出
    public ResultVo exportFile(SelectVo selectVo, HttpServletResponse response) throws Exception {
        //查询数据库
        List<WareHoursePositionVo> wareHoursePositionVoList = wareHoursePositionMapper.queryDataExport(selectVo);
        for (WareHoursePositionVo wareHoursePositionVo : wareHoursePositionVoList) {
            Integer status = wareHoursePositionVo.getStatus() ? 1 : 0;
            if (status == 1) {
                wareHoursePositionVo.setStatusName(StatusEnum.queryById(status));
            } else {
                wareHoursePositionVo.setStatusName(StatusEnum.queryById(status));
            }
        }
        if (wareHoursePositionVoList.size() > 3000) {
            return ResultBuildVo.error("导出数量过多，不能大于3000条");
        }
        //使用poi读取模板数据
        //响应给浏览器的箱子
        ServletOutputStream out = response.getOutputStream();
        //给输出文件设置名称
        POIClass.toPackageOs(response, "库位信息导出");
        //读取模板中的数据
        InputStream in = ExportUtil.toPackageIn("templates/库位.xlsx");
        //把数据写入到模板
        writeDataToExcel(in, "Sheet1", wareHoursePositionVoList, out);
        if (in != null) {
            in.close();
            out.close();
        }
        return null;
    }

    // 由于此方法不能通用, 所以单独写在这里
    private void writeDataToExcel(InputStream in, String sheetName, List<WareHoursePositionVo> resultList, ServletOutputStream out) throws Exception {
        //POi读取模板
        XSSFWorkbook wb = new XSSFWorkbook(in);
        //读取sheet1中的数据
        Sheet sheet = wb.getSheet(sheetName);
        if (sheet != null) {
            //向sheet1中赋值，设置样式
            toResultListValueInfo(sheet, resultList);
        }
        //把数据写入到输出流中
        wb.write(out);
        //关闭poi方法
        wb.close();
    }

    private void toResultListValueInfo(Sheet sheet, List<WareHoursePositionVo> plantList) {
        //从第4行开始赋值
        int row_column = 3;
        int xuhao = 1;
        //遍历数据集合
        for (WareHoursePositionVo obj : plantList) {
            //创建一行的方法
            Row row = sheet.createRow(row_column);
            // 给第一列序号赋值赋值
            POIClass.toCellValue(row, 0, xuhao + "");
            // 给库位编码赋值
            POIClass.toCellValue(row, 1, obj.getCode() + "");
            // 给库位名称赋值
            POIClass.toCellValue(row, 2, obj.getName() + "");
            // 给状态赋值
            POIClass.toCellValue(row, 3, obj.getStatusName() + "");
            // 给库区编码赋值
            POIClass.toCellValue(row, 4, obj.getStorageSectionCode() + "");
            // 给库区名称赋值
            POIClass.toCellValue(row, 5, obj.getStorageSectionName() + "");
            // 给库区描述赋值
            POIClass.toCellValue(row, 6, obj.getStorageSectionRemark() + "");
            // 给库房编码赋值
            POIClass.toCellValue(row, 7, obj.getWareHouseCode() + "");
            // 给库房名称赋值
            POIClass.toCellValue(row, 8, obj.getWareHouseName() + "");
            // 给库房描述赋值
            POIClass.toCellValue(row, 9, obj.getWareHouseRemark() + "");
            row_column++;
            xuhao++;
        }
    }
}
